package com.sanpu.kxe.business.main.presenter;

import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Toast;

import com.linkface.liveness.LFLivenessSDK;
import com.linkface.liveness.network.LFLiDownloadManager;
import com.linkface.liveness.ui.LivenessActivity;
import com.linkface.liveness.util.LFLog;
import com.linkface.liveness.util.LFProtoBufUtil;
import com.sanpu.kxe.R;
import com.sanpu.kxe.business.main.bean.CertificationOutput;
import com.sanpu.kxe.business.main.bean.UserCenterOutput;
import com.sanpu.kxe.business.main.contract.LinkfaceLivenessContract;
import com.sanpu.kxe.business.main.model.MainModel;
import com.sanpu.kxe.business.main.view.MainActivity;
import com.sanpu.kxe.common.cache.CacheManage;
import com.sanpu.kxe.common.cache.CacheModel;
import com.sanpu.kxe.common.interfaces.CommonConfig;
import com.sanpu.kxe.jump.eventbus.RefreshUserEvent;
import com.sanpu.kxe.jump.linkface.Constants;
import com.sanpu.kxe.jump.linkface.LFCommonUtils;
import com.sanpu.kxe.jump.linkface.LFSpUtils;
import com.sanpu.kxe.module.dialog.GlobalDialog;
import com.sanpu.kxe.rxservice.RxError;
import com.sanpu.kxe.utils.AppContextUtil;
import com.sanpu.kxe.utils.FileUtil;
import com.sanpu.kxe.utils.IntentTool;
import com.sanpu.kxe.utils.ToastUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import rx.Observer;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import rx.subscriptions.CompositeSubscription;

import static android.app.Activity.RESULT_CANCELED;
import static com.linkface.liveness.LFLivenessSDK.ERROR_CONTENT_FAILED_NO_LIC_PATH;

/**
 * Description：活体检测
 * Created by 薛勇军 on 2019/5/22.
 */

public class LinkfaceLivenessPresenter implements LinkfaceLivenessContract.Presenter {

    private static final String TAG = "LinkfaceLivenessActivity";

    private LinkfaceLivenessContract.View mView;

    private CompositeSubscription mSubscription;

    private CertificationOutput mCertificationOutput;

    private String protobufPath, protobufName;

    public LinkfaceLivenessPresenter(LinkfaceLivenessContract.View mView, CertificationOutput certificationOutput) {
        this.mView = mView;
        this.mCertificationOutput = certificationOutput;
        mSubscription = new CompositeSubscription();
        protobufPath = CommonConfig.DIR_APP_PROTOBUF + "/";
        protobufName = "livenessDataFile.protobuf";
    }



    @Override
    public void initSDK() {
        //初始化Liveness SDK的License路径
        final String licPath = Constants.LICENSE_MIDDLE_PATH + File.separator + Constants.LICENSE_NAME;
        LFLivenessSDK.getInstance(mView.getContext()).initLicPath(licPath, Constants.LICENSE_NAME);
        try {
            //获取剩余天数
            int remainingDays = LFLivenessSDK.getInstance(mView.getContext()).getRemainingDays();
            //License不在有效期内或到了更新的时间,则启动下载
            if (!LFLivenessSDK.getInstance(mView.getContext()).checkLicenseValid()
                    || remainingDays < Constants.DAYS_BEFORE_LIC_EXPIRED) {
                LFLiDownloadManager.getInstance(
                        mView.getContext()).downLoadLic(Constants.LICENSE_INFO_URL, new LFLiDownloadManager.DownloadListener() {
                    @Override
                    public void onDownload(boolean isSuccess, String errorMsg) {
                        //下载完成的回调
                        LFLog.i(TAG, errorMsg);
                    }
                });
            }
        } catch (IllegalArgumentException e) {
            LFLog.e(TAG, e.getMessage());
        } catch (Exception e) {
            LFLog.e(TAG, e.getMessage());
            Toast.makeText(mView.getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
    }

    @Override
    public void startLiveness() {
        try {
            Bundle bundle = new Bundle();
            /**
             * OUTPUT_TYPE 配置, 传入的outputType类型为singleImg （单图），multiImg （多图），video（低质量视频），fullvideo（高质量视频）
             */
            bundle.putString(LivenessActivity.OUTTYPE, getOutputType());
            /**
             * EXTRA_MOTION_SEQUENCE 动作检测序列配置，支持四种检测动作， BLINK(眨眼), MOUTH（张嘴）, NOD（点头）, YAW（摇头）, 各个动作以空格隔开。 推荐第一个动作为BLINK。
             * 默认配置为"BLINK MOUTH NOD YAW"
             */
            bundle.putString(LivenessActivity.EXTRA_MOTION_SEQUENCE, getActionSequence());
            /**
             * SOUND_NOTICE 配置, 传入的soundNotice为boolean值，true为打开, false为关闭。
             */
            bundle.putBoolean(LivenessActivity.SOUND_NOTICE, LFSpUtils.getMusicTipSwitch(mView.getContext()));
            /**
             * COMPLEXITY 配置, 传入的complexity类型为normal,支持四种难度，easy, normal, hard, hell.
             */
            bundle.putString(LivenessActivity.COMPLEXITY, getComplexity());

            Intent intent = new Intent();
            intent.setClass(mView.getContext(), LivenessActivity.class);
            intent.putExtras(bundle);
            //设置返回图片结果
            intent.putExtra(LivenessActivity.KEY_DETECT_IMAGE_RESULT, true);
            //设置返回protobuf结果
            intent.putExtra(LivenessActivity.KEY_DETECT_PROTO_BUF_RESULT, true);
            //设置返回video结果，video模式才会返回
            intent.putExtra(LivenessActivity.KEY_DETECT_VIDEO_RESULT, true);
            IntentTool.startActivityForResult(mView.getContext(), intent, CommonConfig.KEY_TO_DETECT_REQUEST_CODE);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取设置中设置好的outputType,
     * 若没有设置，默认传入Constants.SINGLEIMG，Constants.MULTIIMG，Constants.VIDEO三个中任意一个
     * 传入的outputType类型为singleImg （单图），multiImg （多图），video（低质量视频），fullvideo（高质量视频）
     * @return
     */
    private String getOutputType() {
        String outputType = Constants.VIDEO;
        outputType = LFSpUtils.getOutputType(mView.getContext(), Constants.FULLVIDEO);
        return outputType;
    }

    /**
     * 获取检测序列
     *
     * @return
     */
    private String getActionSequence() {
        String actionSequence = "";
        //是否使用随机序列
        boolean isRandomSequence = LFSpUtils.getUseRandomSequence(mView.getContext());
        if (isRandomSequence) {
            actionSequence = getRandomSequence();
        } else {
            actionSequence = LFSpUtils.getActionSequence(mView.getContext());
            //如果没有设置动作序列，则使用默认动作序列
            if (TextUtils.isEmpty(actionSequence)) {
                actionSequence = LFCommonUtils.getActionSequence(getDefaultSequenceList());
            }
        }
        return actionSequence;
    }

    /**
     * 获取难易程度，在Constants.EASY，Constants.NORMAL，Constants.HARD，Constants.HELL中选取一个,
     * 默认Constants.NORMAL
     *
     * @return
     */
    private String getComplexity() {
        String complexity = "";
        complexity = LFSpUtils.getComplexity(mView.getContext(), Constants.NORMAL);
        return complexity;
    }

    private String getRandomSequence() {
        Random random = new Random();
        List<String> actionList = new ArrayList<>();
        for (int i = 0; ; i++) {
            int randomAction = random.nextInt(4);
            String actionByPosition = getActionByPosition(randomAction);
            if (!actionList.contains(actionByPosition)) {
                actionList.add(actionByPosition);
                if (actionList.size() >= 4) {
                    break;
                }
            }
        }
        return LFCommonUtils.getActionSequence(actionList);
    }

    private String getActionByPosition(int position) {
        String action = "";
        switch (position) {
            case 0:
                action = Constants.BLINK;
                break;
            case 1:
                action = Constants.MOUTH;
                break;
            case 2:
                action = Constants.NOD;
                break;
            case 3:
                action = Constants.YAW;
                break;
        }
        return action;
    }

    private List<String> getDefaultSequenceList() {
        List<String> sequenceDataList = new ArrayList<>();

        sequenceDataList.add(Constants.BLINK);
        sequenceDataList.add(Constants.MOUTH);
        sequenceDataList.add(Constants.NOD);
        sequenceDataList.add(Constants.YAW);

        return sequenceDataList;
    }

    @Override
    public void dealDetectResult(int resultCode) {
        switch (resultCode) {
            case Activity.RESULT_OK:
                byte[] protobuf = LFProtoBufUtil.getProtoBuf();
                FileUtil.createFileWithByte(protobuf, protobufPath, protobufName);
                File file = new File(protobufPath + protobufName);
                if (file.exists()) {
                    liveness(file);
                } else {
                    ToastUtil.show("人脸数据异常，请重新开始人脸认证");
                }
                break;
            case LivenessActivity.RESULT_SDK_INIT_FAIL_APPLICATION_ID_ERROR:
                ToastUtil.show(Constants.ERROR_PACKAGE);//包名绑定错误
                break;
            case LivenessActivity.RESULT_SDK_INIT_FAIL_LICENSE_OUT_OF_DATE:
                ToastUtil.show(Constants.ERROR_LICENSE_OUT_OF_DATE);//License过期,SDK权限过期
                break;
            case LivenessActivity.RESULT_SDK_INIT_FAIL_OUT_OF_DATE:
                ToastUtil.show(Constants.ERROR_MODEL_LOAD_FAILED);//模型路径错误
                break;
            case LivenessActivity.RESULT_INTERNAL_ERROR:
                ToastUtil.show(Constants.ERROR_SDK_INITIALIZE);//其他错误 文案待定
                break;
            case LivenessActivity.RESULT_CAMERA_ERROR_NOPRERMISSION_OR_USED:
                ToastUtil.show(Constants.ERROR_CAMERA_REFUSE);
                break;
            case LivenessActivity.RESULT_FAILED_NO_LIC_PATH:
                ToastUtil.show(ERROR_CONTENT_FAILED_NO_LIC_PATH);
                break;
            case RESULT_CANCELED:
                ToastUtil.show("检测取消");
                break;
        }
    }

    /**
     * 人脸对比
     */
    private void liveness(File protobufFile) {
        mView.showLoadingDialog(true, "正在进行认证中...");
        Subscription subscription = MainModel.getInstance()
                .liveness(mCertificationOutput, protobufFile)
                .subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onCompleted() {
                        mView.dismissLoadingDialog();
                    }

                    @Override
                    public void onError(Throwable e) {
                        mView.dismissLoadingDialog();
                        if (e instanceof RxError) {
                            RxError rxError = (RxError) e;
                            new GlobalDialog(mView.getContext())
                                    .title("很遗憾，认证失败")
                                    .content(rxError.getMessage())
                                    .headerIcon(R.drawable.img_linkface_fail)
                                    .show();
                        } else {
                            mView.showErrorText(e);
                        }
                    }

                    @Override
                    public void onNext(String s) {
                        UserCenterOutput mOutput = CacheManage.getInstance().getCache(CacheModel.USER_CENTER_KEY);
                        if (mOutput != null) {
                            mOutput.setChkSts(CommonConfig.AUTHEN_PASS);
                        }
                        CacheManage.getInstance().saveCache(CacheModel.USER_CENTER_KEY, mOutput);
                        EventBus.getDefault().post(new RefreshUserEvent());
                        GlobalDialog dialog = new GlobalDialog(mView.getContext())
                                .title("恭喜您，认证成功")
                                .headerIcon(R.drawable.img_linkface_success);
                        dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                                AppContextUtil.finishAllExclByActivity(MainActivity.class.getName());
                            }
                        });
                        dialog.show();
                    }
                });
        mSubscription.add(subscription);
    }

    @Override
    public void onDestroyPresenter() {
        if (mSubscription != null && !mSubscription.isUnsubscribed()) {
            mSubscription.unsubscribe();
            mSubscription = null;
        }
        if (mView != null) {
            mView = null;
        }
    }
}
